package service

import (
	"chat/common"
	"chat/messageType"
	utils "chat/util"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"net/http"
	"nhooyr.io/websocket"
	"sync"
)

type WsStruct struct {
	common.AllCommonStruct
	Message       string `gorm:"size:500;notnull;comment:用户发送的消息" json:"message"`
	MessageType   uint   `gorm:"notnull;comment:发送的消息类型" json:"messageType"`
	Nick          string `gorm:"size:16;notnull;comment:用户昵称" json:"nick"`
	UserPic       string `gorm:"-;comment:用户头像" json:"userPic"`
	FromUserId    uint32 `gorm:"comment:发送消息的用户" json:"fromUserId"`
	ToUserId      uint32 `gorm:"comment:接收消息的用户" json:"toUserId"`
	GroupId       uint32 `gorm:"comment:接收消息的群组" json:"groupId"`
	Revoke        uint8  `gorm:"comment:是否撤回消息0-未撤回，1已撤回" json:"revoke"`
	Secret        string `gorm:"-;comment:用户密钥" json:"secret"`
	BeforeGroupId uint32 `gorm:"-" json:"beforeGroupId"`
}
type WsUser struct {
	UserId uint32          `json:"userId"`
	Conn   *websocket.Conn `json:"conn"`
}
type Room struct {
	RoomNo uint32 `json:"roomNo"`
}

var WSMap = make(map[uint32][]*WsUser)
var mutex sync.Mutex
var roomList []*Room

func (w *WsStruct) GetRoomList(db *gorm.DB) {
	err := db.Table("user").Find(&roomList).Error
	if err != nil {
		fmt.Println(err)
	}
	for _, v := range roomList {
		WSMap[v.RoomNo] = []*WsUser{}
	}
}
func (w *WsStruct) TableName() string {
	return "message_list"
}
func (w *WsStruct) Ws(context *gin.Context, db *gorm.DB) {
	var uService UserService
	accept, err := websocket.Accept(context.Writer, context.Request, &websocket.AcceptOptions{InsecureSkipVerify: true})
	if err != nil {
		fmt.Println("socket error", err)
		return
	}
	for {
		MType, message, err := accept.Read(context.Request.Context())
		if err != nil {
			fmt.Println("reader error", err)
			return
		}
		if MType == websocket.MessageText {
			var m WsStruct
			err := json.Unmarshal(message, &m)
			if err != nil {
				context.JSON(http.StatusInternalServerError, gin.H{
					"message": err.Error(),
				})
				context.Abort()
				return
			}
			switch m.MessageType {
			case messageType.LOGIN:
				fmt.Println(123, m)
				rows := db.Debug().Table("user").Where("id=? AND socket_sign=?", m.FromUserId, m.Secret).Find(&uService)
				var messageList []WsStruct
				if rows.RowsAffected > 0 {
					mutex.Lock()
					u := &WsUser{
						UserId: m.FromUserId,
						Conn:   accept,
					}
					if m.GroupId == 0 {
						m.GroupId = 1001
					}
					msg := WsStruct{
						Message:     fmt.Sprintf("用户-%s加入此房间", uService.Nick),
						MessageType: messageType.MESSAGETEXTFORGroup,
						FromUserId:  m.FromUserId,
						Nick:        uService.Nick,
						UserPic:     uService.UserPic,
						ToUserId:    0,
						GroupId:     m.GroupId,
					}
					marshal, err := json.Marshal(msg)
					if err != nil {
						return
					}
					var uSlice []*WsUser
					for _, v := range WSMap[m.GroupId] {
						if v.UserId != m.FromUserId {
							uSlice = append(uSlice, v)
						}
					}
					db.Debug().Table(w.TableName()).Where("`group_id`=? AND `revoke`=?", m.GroupId, 0).Find(&messageList)
					WSMap[m.GroupId] = append(uSlice, u)
					for _, v := range WSMap[m.GroupId] {
						if v.UserId == m.FromUserId {
							data, _ := json.Marshal(messageList)
							_ = v.Conn.Write(context.Request.Context(), MType, data)

						}
						err = v.Conn.Write(context.Request.Context(), MType, marshal)
						if err != nil {
							fmt.Println(22222, err)
						}

					}
					// 广播消息
					mutex.Unlock()
				} else {
					fmt.Println(33333)
					utils.Result(http.StatusBadRequest, nil, context)
					context.Abort()
					return
				}
				break
			case messageType.HEART:

				break
			case messageType.LOGOUT:
				mutex.Lock()
				//userList := WSMap[m.GroupId]

				mutex.Unlock()
				break
			case messageType.MESSAGETEXTFORGroup:
				fmt.Println(m, uService, 33333)
				_ = db.Debug().Table("user").Where("id=?", m.FromUserId).Find(&uService)
				if m.GroupId == 0 {
					m.GroupId = 1001
				}
				var msg = WsStruct{
					AllCommonStruct: common.AllCommonStruct{},
					Message:         m.Message,
					MessageType:     m.MessageType,
					FromUserId:      m.FromUserId,
					Nick:            uService.Nick,
					UserPic:         uService.UserPic,
					GroupId:         m.GroupId,
				}
				db.Debug().Table(w.TableName()).Create(&msg).Order("created_at desc").Find(&msg)
				marshal, err := json.Marshal(msg)
				if err != nil {
					fmt.Println(11111, err)
					return
				}
				for _, v := range WSMap[m.GroupId] {
					err := v.Conn.Write(context.Request.Context(), MType, marshal)
					if err != nil {
						fmt.Println("group err", err)
						return
					}
				}
				break
			case messageType.MESSAGETEXTFORUSER:

				break
			case messageType.MESSAGECHANGEROOM:
				fmt.Println(m.BeforeGroupId, m.GroupId, m, m.FromUserId)
				if m.BeforeGroupId > 0 && m.GroupId > 0 {
					var messageList []WsStruct
					mutex.Lock()
					beforeUser := WSMap[m.BeforeGroupId]
					var uSlice []*WsUser // 将添加得到新group
					var uSlice2 []*WsUser
					for _, v := range beforeUser {
						fmt.Println(v)
						if v.UserId == m.FromUserId {
							uSlice = append(uSlice, v)
						} else {
							uSlice2 = append(uSlice2, v)
						}
					}
					fmt.Println(uSlice, beforeUser)
					var newUSlice []*WsUser
					WSMap[m.BeforeGroupId] = uSlice2
					newUser := WSMap[m.GroupId]

					for _, v := range newUser {
						if v.UserId != m.FromUserId {
							newUSlice = append(newUSlice, v)
						}
					}
					newUSlice = append(newUSlice, uSlice...)
					WSMap[m.GroupId] = newUSlice
					msg := WsStruct{
						Message:     fmt.Sprintf("用户-%s加入此房间", uService.Nick),
						MessageType: messageType.MESSAGETEXTFORGroup,
						FromUserId:  m.FromUserId,
						Nick:        uService.Nick,
						UserPic:     uService.UserPic,
						ToUserId:    0,
						GroupId:     m.GroupId,
					}
					marshal, err := json.Marshal(msg)
					if err != nil {
						return
					}
					db.Debug().Table(w.TableName()).Where("`group_id`=? AND `revoke`=?", m.GroupId, 0).Find(&messageList)
					for _, v := range WSMap[m.GroupId] {
						if v.UserId == m.FromUserId {
							data, _ := json.Marshal(messageList)
							_ = v.Conn.Write(context.Request.Context(), MType, data)

						}
						err = v.Conn.Write(context.Request.Context(), MType, marshal)
						if err != nil {
							fmt.Println(22222, err)
						}

					}
					mutex.Unlock()
				}

				break
			}
		}
	}
}
